﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Xml;
using shelltwitlib.Web;
using shelltwitlib.xAuth;

namespace shelltwitlib.Status
{
	public class Update
	{
		const string OAUTH_UPDATE_STATUS = "http://api.twitter.com/1/statuses/update.xml";
		const string STATUS = "status";

		public static string UpdateStatus(string status)
		{
			if (status.Length > 140)
				throw new Exception("status must be at most 140 characters long");

			TwitterUser user = TwitterUser.LoadCredentials();
			string encodedStatus = Util.EncodeString(status);
			
			HttpWebRequest req = GetUpdateStatusRequest(user.OAuthToken, user.OAuthTokenSecret, encodedStatus);

			byte[] bytes = Util.GetUTF8EncodingBytes(string.Format("{0}={1}", STATUS, encodedStatus));

			req.ContentLength = bytes.Length;
			using (Stream str = req.GetRequestStream())
				str.Write(bytes, 0, bytes.Length);

			HttpWebResponse response = (HttpWebResponse)req.GetResponse();

			if (response.StatusCode != HttpStatusCode.OK)
				return response.StatusDescription;

			string data = string.Empty;
			using (StreamReader reader = new StreamReader(response.GetResponseStream()))
				data = reader.ReadToEnd();

			XmlDocument doc = new XmlDocument();
			try
			{
				doc.LoadXml(data);
			}
			catch
			{
				doc = null;
			}

			if (doc == null)
				return data;
			else
				return response.StatusDescription;
		}

		static HttpWebRequest GetUpdateStatusRequest(string oAuthToken, string oAuthSecret, string encodedStatus)
		{
			HttpWebRequest request = (HttpWebRequest)WebRequest.Create(OAUTH_UPDATE_STATUS);
			request.Method = HttpMethod.POST.ToString();

			string nonce = OAuthHelper.GetNonce();
			string timestamp = OAuthHelper.GetTimestamp();

			Dictionary<string, string> parms = GetUpdateStatusParms(nonce, timestamp, oAuthToken, encodedStatus);
			string signatureBase = OAuthHelper.SignatureBsseString(request.Method, OAUTH_UPDATE_STATUS, parms);
			string signature = OAuthHelper.SignBaseString(signatureBase, oAuthSecret);
			string authHeader = OAuthHelper.AuthorizationHeader(nonce, signature, timestamp, oAuthToken);

			request.Headers.Add(Constants.AUTHORIZATION, authHeader);
			request.ContentType = Constants.CONTENT_TYPE;
			request.ServicePoint.Expect100Continue = false;
			request.UserAgent = Constants.USER_AGENT;

			return request;
		}

		static Dictionary<string, string> GetUpdateStatusParms(string nonce, string timestamp, string oAuthToken, string status)
		{
			Dictionary<string, string> dic = new Dictionary<string, string>();
			dic.Add(OAuthHelper.OAUTH_CONSUMER_KEY, Util.EncodeString(OAuthData.CONSUMER_KEY));
			dic.Add(OAuthHelper.OAUTH_NONCE, nonce);
			dic.Add(OAuthHelper.OAUTH_SIGNATURE_METHOD, OAuthHelper.HMAC_SHA1);
			dic.Add(OAuthHelper.OAUTH_TIMESTAMP, timestamp);
			dic.Add(OAuthHelper.OAUTH_VERSION, OAuthHelper.OAUTH_VERSION_10);
			dic.Add(OAuthHelper.OAUTH_TOKEN, oAuthToken);
			dic.Add(STATUS, status);

			return dic;
		}
	}
}
